
package com.idealighter.game.roomcard.games.mustniuniu.struct;

import com.idealighter.game.games.common.SeatState;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.roomcard.common.AbstractRoomCardTable;
import com.idealighter.game.roomcard.games.mustniuniu.bo.TrusteeBo;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuAdvanceOption;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuCardType;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuGame;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuGameState;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MultipleOptionPo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuAdvanceOptionPo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuBankerChipPo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuBetOptionPo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuCallBankerMultiplePo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuCardMultiplePo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuCardSpecialMultiplePo;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue.MustNiuNiuExtrBetOptionPo;
import com.idealighter.game.roomcard.struct.roomcfg.MustNiuNiuRoomCardRoomCfg;
import com.idealighter.game.roomcard.struct.roomcfg.value.MustNiuNiuRoomCardRoomCfgValue;
import com.idealighter.game.server.db.datadb.generate.domain.RoomCardNiuniuScoreDetailsDomain;
import com.idealighter.utils.check.EmptyUtil;
import com.idealighter.utils.code.RandCodeUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 四人牛牛桌子 .
 * 
 * @date 2016年1月20日 下午5:08:54
 *
 */

@Data
@EqualsAndHashCode(callSuper = true)
public class MustNiuNiuTable extends AbstractRoomCardTable<MustNiuNiuSeat, //
    MustNiuNiuRoomCardRoomCfg, MustNiuNiuRoomCardRoomCfgValue> {
  // 桌子是否准备完成
  private boolean readied = false;
  // 游戏阶段
  private MustNiuNiuGameState status = MustNiuNiuGameState.NO_START;
  // 叫庄倍数
  private int callDealerMultiple = 0;
  // 主流程定时执行器
  public ScheduledFuture<?> stepFuture = null;
  // 托管定时器
  public ScheduledFuture<?> trusteeFuture = null;
  // 一副牌
  private final List<NiuNiuCard> cards = new ArrayList<NiuNiuCard>();
  // 支持的玩法和倍数
  private final Map<MustNiuNiuCardType, Integer> cardTypeMap = new HashMap<>();
  // 得分详情
  private List<RoomCardNiuniuScoreDetailsDomain> scoreDetails = new ArrayList<>();
  // 托管玩家
  private Map<Long, TrusteeBo> trustees = new HashMap<Long, TrusteeBo>();
  // 上一把含有牛牛牌的玩家列表，用户牛牛坐庄产生庄家
  private List<Long> niuNiuCardTypePlayers = new ArrayList<Long>();
  // 上一把庄家编号
  private Long preDealerId = 0L;

  /**
   * 构造函数 .
   * 
   * @param room .
   */
  public MustNiuNiuTable(MustNiuNiuRoom room) {
    super(room);
    init(room);
  }

  private void init(MustNiuNiuRoom room) {
    MustNiuNiuRoomCardRoomCfgValue cfgValue = room.getRoomCfg().cfgs();
    boolean joker = false; // 是否支持王牌癞子
    List<MustNiuNiuAdvanceOptionPo> advanceOptions = cfgValue.getAdvanceOptions();
    if (EmptyUtil.listIsNotEmpty(advanceOptions)) {
      for (MustNiuNiuAdvanceOptionPo item : advanceOptions) {
        if (item.getId() == MustNiuNiuAdvanceOption.JOKER.id) {
          joker = true;
          break;
        }
      }
    }

    List<NiuNiuCard> tmpCards = new ArrayList<>();
    for (NiuNiuCard item : NiuNiuCard.values()) {
      if (!joker) {
        if (item.ordinal() == NiuNiuCard.XIAO_WANG.ordinal()) {
          continue;
        }
        if (item.ordinal() == NiuNiuCard.DA_WANG.ordinal()) {
          continue;
        }
      }
      tmpCards.add(item);
    }
    cards.addAll(tmpCards);

    // 牌型和倍数
    MustNiuNiuCardMultiplePo multiples = cfgValue.getMultiple();
    for (MultipleOptionPo item : multiples.getMultiples()) {
      cardTypeMap.put(MustNiuNiuCardType.geCardsType(item.getNiu()), item.getMultiple());
    }
    // 特殊牌型和倍数
    List<MustNiuNiuCardSpecialMultiplePo> specialMultipleList = cfgValue.getSpecialMultiples();
    if (EmptyUtil.listIsNotEmpty(specialMultipleList)) {
      for (MustNiuNiuCardSpecialMultiplePo item : specialMultipleList) {
        cardTypeMap.put(MustNiuNiuCardType.geCardsType(item.getNiu()), item.getMultiple());
      }
    }
  }

  public boolean isNiuNiuBeBanker() {
    int type = room().getRoomCfg().cfgs().getType();
    return type == MustNiuNiuGame.NIUNIU_BE_BANKER.intValue();
  }

  public boolean isOwnerBeBanker() {
    int type = room().getRoomCfg().cfgs().getType();
    return type == MustNiuNiuGame.OWNER_BE_BANKER.intValue();
  }

  public boolean isFreeCallBanker() {
    int type = room().getRoomCfg().cfgs().getType();
    return type == MustNiuNiuGame.FREE_CALL_BANKER.intValue();
  }

  public boolean isShowCardCallBanker() {
    int type = room().getRoomCfg().cfgs().getType();
    return type == MustNiuNiuGame.SHOW_CARD_CALL_BANKER.intValue();
  }

  public MustNiuNiuExtrBetOptionPo findExtrBetOptionPo() {
    return room().getRoomCfg().cfgs().getExtrBetOption();
  }

  public MustNiuNiuBankerChipPo findBankerChipPo() {

    return room().getRoomCfg().cfgs().getBankerChip();
  }

  public MustNiuNiuCallBankerMultiplePo findMaxCallBankerMultiple() {
    return room().getRoomCfg().cfgs().getCallBankerMultiple();
  }

  /**
   * @Title findAdvanceOptionPo.
   * @Description 获取高级选项
   * @date 2018年6月9日 上午9:13:06
   * @param advanceOption 高级选项
   * @return .
   */
  public MustNiuNiuAdvanceOptionPo findAdvanceOptionPo(MustNiuNiuAdvanceOption advanceOption) {
    MustNiuNiuAdvanceOptionPo result = null;
    List<MustNiuNiuAdvanceOptionPo> list = room().getRoomCfg().cfgs().getAdvanceOptions();
    if (EmptyUtil.listIsNotEmpty(list)) {
      for (MustNiuNiuAdvanceOptionPo item : list) {
        if (item.getId() == advanceOption.id) {
          result = item;
          break;
        }
      }
    }
    return result;
  }

  /**
   * @Title findAdvanceOptionPo.
   * @Description 获取高级选项
   * @date 2018年6月9日 上午9:13:32
   * @param advanceOptions 高级选项列表
   * @return .
   */
  public List<MustNiuNiuAdvanceOptionPo> findAdvanceOptionPo(
      List<MustNiuNiuAdvanceOption> advanceOptions) {
    List<MustNiuNiuAdvanceOptionPo> list = room().getRoomCfg().cfgs().getAdvanceOptions();
    List<MustNiuNiuAdvanceOptionPo> result = new ArrayList<MustNiuNiuAdvanceOptionPo>();
    if (EmptyUtil.listIsNotEmpty(list)) {
      for (MustNiuNiuAdvanceOptionPo item : list) {
        for (MustNiuNiuAdvanceOption option : advanceOptions) {
          if (option.id == item.getId()) {
            result.add(item);
          }
        }
      }
    }
    return result;
  }

  /**
   * @Title findAdvanceOptionPoByIds.
   * @Description 获取高级选项
   * @date 2018年6月9日 上午9:13:32
   * @param ids 高级选项编号列表
   * @return .
   */
  public List<MustNiuNiuAdvanceOptionPo> findAdvanceOptionPoByIds(List<Integer> ids) {
    List<MustNiuNiuAdvanceOptionPo> list = room().getRoomCfg().cfgs().getAdvanceOptions();
    List<MustNiuNiuAdvanceOptionPo> result = new ArrayList<MustNiuNiuAdvanceOptionPo>();
    if (EmptyUtil.listIsNotEmpty(list)) {
      for (MustNiuNiuAdvanceOptionPo item : list) {
        for (Integer id : ids) {
          if (id == item.getId()) {
            result.add(item);
          }
        }
      }
    }
    return result;
  }

  public MustNiuNiuBetOptionPo findBetOptionPo() {
    return room().getRoomCfg().cfgs().getBetOption();
  }

  /**
   * 重置桌子 .
   */
  public void reset() {
    this.readied = false;
    this.callDealerMultiple = 0;
  }

  /**
   * 闲家合计筹码 .
   * 
   * @return .
   */
  public long playesChips() {
    long playesChips = 0;
    for (MustNiuNiuSeat s : this.seats()) {
      if (!s.isDealer() && s.getPlayerId() > 0) {
        playesChips += s.getTotalChips();
      }
    }

    return playesChips;
  }

  /**
   * 随机产生庄家 .
   * 
   * @return .
   */
  public MustNiuNiuSeat randCallDealerSeat() {
    // 叫庄玩家
    List<MustNiuNiuSeat> callDealerSeats = new ArrayList<>();
    int maxMultiple = 0; // 最高叫庄倍数
    for (MustNiuNiuSeat s : this.getGameSeats(true)) {
      if (s.getState() == SeatState.GAMING && s.getCallDealerMultiple() != null) {
        // 如果叫庄倍数比最之前的大，清空叫庄人
        if (s.getCallDealerMultiple() > maxMultiple) {
          callDealerSeats.clear();
          maxMultiple = s.getCallDealerMultiple();
        }
        if (s.getCallDealerMultiple() >= maxMultiple) {
          callDealerSeats.add(s);
        }
      }
    }

    // 随机生成一位庄家
    return RandCodeUtil.randomList(callDealerSeats);
  }

  /**
   * 牌桌是否全部摊牌 .
   * 
   * @return .
   */
  public boolean showdown() {
    for (MustNiuNiuSeat s : this.getGameSeats(true)) {
      if (s.getState().equals(SeatState.GAMING) && !s.isShowdown()) {
        return false;
      }
    }

    return true;
  }

  /**
   * 叫庄是否结束,所有人都叫过庄且人数超过1个 .
   * 
   * @return .
   */
  public boolean callDealerOver() {
    long callDealerNum = 0;
    for (MustNiuNiuSeat s : this.getGameSeats(true)) {
      if (s.getPlayerId() > 0 && s.getState() == SeatState.GAMING) {
        if (s.getCallDealerMultiple() == null) {
          return false;
        }
        callDealerNum++;
      }
    }

    if (callDealerNum <= 1) {
      return false;
    }

    return true;
  }

  /**
   * 牌桌是否下注结束 .
   * 
   * @return .
   */
  public boolean betOver() {
    MustNiuNiuSeat dealer = dealer();
    MustNiuNiuAdvanceOptionPo betOtherOption =
        findAdvanceOptionPo(MustNiuNiuAdvanceOption.BET_OTHER);
    int count = 0; // 闲家数量
    int nullBetOtherPlayerNum = 0; // 尚未买码的玩家编号
    for (MustNiuNiuSeat s : this.getGameSeats(true)) {
      if (s.getState() == SeatState.GAMING // 正在游戏中的玩家
          && s.getPlayerId() != dealer.getPlayerId()) { // 非庄家
        if (s.getBetedchips() == 0L) {
          return false;
        }
        count++;
        if (betOtherOption != null) {
          // 尚未买码玩家数量
          if (s.getBetOtherPlayerId() == null) {
            nullBetOtherPlayerNum++;
          }
          // 如果含有多个闲家，且至少含有一个未买码，则下注尚未结束
          if (count > 1 && nullBetOtherPlayerNum > 0) {
            return false;
          }
        }
      }
    }

    return true;
  }

  /**
   * 返回庄家 .
   * 
   * @return .
   */
  public MustNiuNiuSeat dealer() {
    for (MustNiuNiuSeat seat : this.getGameSeats(true)) {
      if (!seat.isByStander() && seat.isDealer()) {
        return seat;
      }
    }
    return null;
  }

  @Override
  protected MustNiuNiuSeat createSeat(AbstractRoomCardTable<MustNiuNiuSeat, //
      MustNiuNiuRoomCardRoomCfg, MustNiuNiuRoomCardRoomCfgValue> table, int order) {
    return new MustNiuNiuSeat(order, (MustNiuNiuTable) table);
  }

  @Override
  public MustNiuNiuRoom room() {
    return (MustNiuNiuRoom) super.room();
  }

}
